#include "vzconn/conn/tcpserver.h"
#include "vzconn/base/helper.h"

namespace vzconn {

TcpServer::TcpServer(boost::asio::io_service &io_service,
                     const std::string addr,
                     uint16 port)
  : VzServer(io_service),
    bind_addr_(boost::asio::ip::tcp::endpoint(
                 boost::asio::ip::address().from_string(addr), port)),
    stop_(false) {
}

TcpServer::~TcpServer() {
}

bool TcpServer::Start() {
  if (stop_) {
    LOG(ERROR) << "The TcpServer is not stop, you should not Start agian";
    return false;
  }
  try {
    acceptor_.reset(new boost::asio::ip::tcp::acceptor(
                      io_service_,
                      bind_addr_.protocol()));
    acceptor_->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
    // TODO BUG?
    acceptor_->bind(bind_addr_);
    acceptor_->listen();
    stop_ = false;
    io_service_.post(
      boost::bind(&VzServer::WaitNextConnect, shared_from_this()));
  } catch (std::exception& e) {
    LOG(ERROR) << e.what();
    return false;
  }
  return true;
}

const std::string TcpServer::bind_addr() const {
  return bind_addr_.address().to_string();
}

void TcpServer::WaitNextConnect() {
  if (stop_) {
    LOG(WARNING) << "The TcpServer was stoped";
    return;
  }
  if (!acceptor_) {
    LOG(ERROR) << "The Acceptor is null";
    return;
  }

  TcpConnect *conn = new TcpConnect(io_service_);
  VzConnect::Ptr tcp_connect(conn);
  acceptor_->async_accept(conn->socket(),
                          boost::bind(&TcpServer::HandleAcceptor,
                                      shared_from_this(),
                                      tcp_connect,
                                      boost::asio::placeholders::error));
}

void TcpServer::HandleStopVzServer() {
  if (acceptor_->is_open()) {
    acceptor_->close();
  }
}

}